package com.samp.bblock.core.web.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.samp.bblock.core.exception.WebException;
import com.samp.bblock.core.web.bind.json.JsonBindSupport;

public class JsonHttpServletRequestWrapper extends HttpServletRequestWrapper {
	
	private static final Logger logger = LoggerFactory.getLogger(JsonHttpServletRequestWrapper.class);

	private Map<String, String[]> paramsList;
	
	public JsonHttpServletRequestWrapper(HttpServletRequest request) {
		super(request);
	}
	
	public JsonHttpServletRequestWrapper(HttpServletRequest request, Map jsonMap) throws WebException{
		super(request);
		if( jsonMap != null && jsonMap.size() > 0 ){
			JsonToFormParamsUtils utils = new JsonToFormParamsUtils();
			this.paramsList = utils.toHttpParams(jsonMap);
			this.paramsList.putAll(getRequest().getParameterMap());
		}else{
			this.paramsList = request.getParameterMap();
		}
	}

	@Override
	public String getParameter(String name) {
		String[] v = (String[])getParamsList().get(name);
		if( v != null && v.length > 0 ){
			return v[0];
		}
		return null;
}

	@Override
	public Map<String, String[]> getParameterMap() {
		return getParamsList();
	}

	@Override
	public Enumeration<String> getParameterNames() {
		return new KeyEnumeration(getParamsList().keySet());
	}

	@Override
	public String[] getParameterValues(String name) {
		return (String[])getParamsList().get(name);
	}

	private Map<String,String[]> getParamsList(){
		if( this.paramsList == null ){
			this.paramsList = getRequest().getParameterMap();
			Map tempList = _read();
			if( tempList != null && tempList.size() > 0 ){
				tempList.putAll(this.paramsList);
				this.paramsList = tempList;
			}
		}
		return this.paramsList;
	}
	
	private Map<String, String[]> _read(){
		String requestParams = null;
		try {
			BufferedReader in = getReader();
			StringWriter out = new StringWriter(128);
			char[] buffer = new char[512];
			int bytesRead = -1;
			while( (bytesRead = in.read(buffer)) != -1) {
				out.write(buffer, 0, bytesRead);
			}
			requestParams = out.toString();
		} catch (IOException e) {
			logger.error("error ",e);
			throw new WebException(e.getMessage(),e);
		}
		if( StringUtils.hasText(requestParams) ){
			logger.debug("jsonParams = "+requestParams);
			Map jsonMap = null;
			try{
				jsonMap = JsonBindSupport.getInstance().toMap(requestParams);
			}catch(Exception e){
				throw new WebException("PostJson["+requestParams+"] format error:"+e.getMessage(), e);
			}
			JsonToFormParamsUtils utils = new JsonToFormParamsUtils();
			return utils.toHttpParams(jsonMap);
		}
		logger.debug("JsonParams={}");
		return null;
	}
	
	class KeyEnumeration implements Enumeration<String>{
		
		private Iterator<String> iterator;
		private Set<String> keySet;
		
		public KeyEnumeration(Set<String> keySet){
			this.keySet = keySet;
		}
		

		@Override
		public boolean hasMoreElements() {
			return getIterator().hasNext();
		}

		@Override
		public String nextElement() {
			return (String)getIterator().next();
		}
		
		public String toString(){
			return this.keySet.toString();
		}
		
		private Iterator<String> getIterator(){
			if( this.iterator == null ){
				this.iterator = this.keySet.iterator();
			}
			return this.iterator;
		}
		
	}
	
}
